#include "grammar.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

/* Functions */
FILE *getInput(int argc, char *argv[]);
char getChar();
int isTheInputChar(char testChar);
void getSymbol();
int getDerivationSymbol();
void getGrammarDerivation();
void buildGrammar();

/* Global Variables */
FILE *inputFile;
char currentChar;
char currentSymbol[40];
grammarSymbolsList currentConcatDerivation;
rightSideGrammarDerivation currentUnionDerivations;
grammarDerivationsList grammar;


int main(int argc, char *argv[])
{
	if(inputFile = getInput(argc, argv))
	{
		buildGrammar();
		//removeSimpleLeftRec(&grammar, "teste");		
		removeLeftRec(&grammar);
		printGrammarDerivations(grammar);		
	}
	return 0;
}

FILE *getInput(int argc, char *argv[])
{	
	if(argc > 1)
	{	
		FILE *fp = fopen(argv[1], "r");
		if(fp)		
			return fp;
		
		else
			printf("File \"%s\" does not exist\n", argv[1]);
	}
	else
		printf("Please specify a grammar filename\n");
	return NULL;	
}

char getChar()
{
	if(currentChar != EOF)
		currentChar = fgetc(inputFile);
	return currentChar;
}

int isTheInputChar(char testChar)
{
	if(currentChar == testChar)
		return 1;
	return 0;
}

void getSymbol()
{
	int i = 0;
	getChar();
	while(!isTheInputChar('>'))
	{
		currentSymbol[i++] = currentChar;
		getChar();
	}
	currentSymbol[i] = '\0';
}

int getDerivationSymbol()
{
	getChar();
	while(!isTheInputChar(':'))
		getChar();
	getChar();
	if(isTheInputChar(':'))
	{
		getChar();
		if(isTheInputChar('='))
			return 1;
	}
	return 0;
}

void getGrammarDerivation()
{
	char firstSymbolName[40];
	getSymbol();
	strcpy(firstSymbolName, currentSymbol);	
	if(getDerivationSymbol())
	{
		currentUnionDerivations = NULL;
		currentConcatDerivation = NULL;
		do
		{
			getChar();
			if(currentChar == '<')
			{
				getSymbol();
				addGrammarSymbolsList(&currentConcatDerivation, currentSymbol);
			}
			else if(currentChar == '|')
			{
				addUnion(&currentUnionDerivations, currentConcatDerivation);
				currentConcatDerivation = NULL;				
			}
		} while(currentChar != ';');
		if(currentConcatDerivation != NULL)
			addUnion(&currentUnionDerivations, currentConcatDerivation);
		addGrammarDerivation(&grammar, currentUnionDerivations, firstSymbolName);
	}
}

void buildGrammar()
{
	while(getChar() != EOF)
	{
		if(currentChar == '<')
			getGrammarDerivation();
	} 
}
